package com.fary.mergedbean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class MyMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {

    //bean名字对应的注解方法
    public Map<String, List<Method>> stringMethodMap;

    private Class<? extends Annotation> myAnnotationType;

    public MyMergedBeanDefinitionPostProcessor() {
        myAnnotationType = MyAnnotation.class;
        stringMethodMap = new HashMap<>();

    }

    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        List<Method> list = new ArrayList<>();
        ReflectionUtils.doWithLocalMethods(beanType, method -> {
            if (this.myAnnotationType != null && method.isAnnotationPresent(this.myAnnotationType)) {
                list.add(method);
                stringMethodMap.put(beanName, list);
            }
        });
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (stringMethodMap.get(beanName) != null) {
            for (Method method : stringMethodMap.get(beanName)) {
                try {
                    MyAnnotation annotation = (MyAnnotation) method.getAnnotation(this.myAnnotationType);
                    for (int i = 0; i < annotation.count(); i++) {
                        method.invoke(bean, new Object[]{method.getName()});
                    }
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
        return bean;
    }
}
